package com.school.sports.websocket;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 系统消息WebSocket服务器端点
 * 用于处理系统消息的实时状态更新
 *
 * @author 系统管理员
 * @version 1.0
 * @since 2023-10-12
 */
@Slf4j
@Component
@ServerEndpoint("/websocket/system-message/{adminId}")
public class SystemMessageWebSocketServer {

    // 静态变量，用来记录当前在线连接数
    private static final AtomicInteger onlineCount = new AtomicInteger(0);

    // concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketServer对象
    private static final ConcurrentHashMap<String, SystemMessageWebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    // 与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;

    // 接收adminId
    private String adminId = "";

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("adminId") String adminId) {
        this.session = session;
        this.adminId = adminId;

        // 检查是否已存在连接
        if (webSocketMap.containsKey(adminId)) {
            // 如果已存在，先关闭旧连接
            SystemMessageWebSocketServer oldServer = webSocketMap.get(adminId);
            if (oldServer != null) {
                try {
                    oldServer.session.close();
                } catch (IOException e) {
                    log.error("关闭旧连接失败", e);
                }
            }
        }

        webSocketMap.put(adminId, this);
        onlineCount.incrementAndGet();

        log.info("系统消息管理员连接:{}, 当前在线管理员数:{}", adminId, onlineCount.get());

        // 发送连接成功消息
        try {
            JSONObject message = new JSONObject();
            message.put("type", "connection");
            message.put("status", "connected");
            message.put("message", "系统消息连接成功");
            sendMessage(message.toJSONString());
        } catch (IOException e) {
            log.error("系统消息管理员:{} 网络异常!", adminId, e);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (webSocketMap.containsKey(adminId)) {
            webSocketMap.remove(adminId);
            onlineCount.decrementAndGet();
        }
        log.info("系统消息管理员退出:{}, 当前在线管理员数:{}", adminId, onlineCount.get());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("系统消息管理员消息:{}, 报文:{}", adminId, message);

        try {
            JSONObject jsonObject = JSON.parseObject(message);
            String type = jsonObject.getString("type");

            switch (type) {
                case "heartbeat":
                    // 心跳检测
                    sendHeartbeatResponse();
                    break;
                default:
                    log.warn("未知消息类型: {}", type);
            }
        } catch (Exception e) {
            log.error("处理系统消息管理员消息异常", e);
        }
    }

    /**
     * 发送心跳响应
     */
    private void sendHeartbeatResponse() {
        try {
            JSONObject response = new JSONObject();
            response.put("type", "heartbeat");
            response.put("timestamp", System.currentTimeMillis());
            sendMessage(response.toJSONString());
        } catch (Exception e) {
            log.error("发送心跳响应失败", e);
        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("系统消息管理员错误:{}, 原因:{}", this.adminId, error.getMessage(), error);
    }

    /**
     * 实现服务器主动推送消息
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 发送自定义消息
     */
    public static void sendInfo(String message, @PathParam("adminId") String adminId) throws IOException {
        log.info("发送消息到系统消息管理员:{}, 报文:{}", adminId, message);
        if (adminId != null && webSocketMap.containsKey(adminId)) {
            webSocketMap.get(adminId).sendMessage(message);
        } else {
            log.error("系统消息管理员{}不在线", adminId);
        }
    }

    /**
     * 群发自定义消息给所有管理员
     */
    public static void sendAllAdminMessage(String message) {
        log.info("群发系统消息给管理员: {}", message);
        webSocketMap.forEach((adminId, webSocketServer) -> {
            try {
                webSocketServer.sendMessage(message);
            } catch (IOException e) {
                log.error("群发系统消息失败，管理员:{}", adminId, e);
            }
        });
    }

    /**
     * 发送消息状态更新
     */
    public static void sendMessageStatusUpdate(Long messageId, String title, String status, String sendTime, Integer recipientCount) {
        JSONObject notification = new JSONObject();
        notification.put("type", "message_status_update");

        JSONObject payload = new JSONObject();
        payload.put("messageId", messageId);
        payload.put("title", title);
        payload.put("status", status);
        if (sendTime != null) {
            payload.put("sendTime", sendTime);
        }
        if (recipientCount != null) {
            payload.put("recipientCount", recipientCount);
        }

        notification.put("payload", payload);

        String messageJson = notification.toJSONString();
        sendAllAdminMessage(messageJson);
    }

    /**
     * 发送新系统消息通知
     */
    public static void sendNewSystemMessage(Long messageId, String title, String messageType, String priority) {
        JSONObject notification = new JSONObject();
        notification.put("type", "new_system_message");

        JSONObject payload = new JSONObject();
        payload.put("id", messageId);
        payload.put("title", title);
        payload.put("messageType", messageType);
        payload.put("priority", priority);

        notification.put("payload", payload);

        String messageJson = notification.toJSONString();
        sendAllAdminMessage(messageJson);
    }

    /**
     * 发送消息统计数据
     */
    public static void sendMessageStatistics(int totalMessages, int sentMessages, int pendingMessages, int failedMessages) {
        JSONObject notification = new JSONObject();
        notification.put("type", "message_statistics");

        JSONObject payload = new JSONObject();
        payload.put("totalMessages", totalMessages);
        payload.put("sentMessages", sentMessages);
        payload.put("pendingMessages", pendingMessages);
        payload.put("failedMessages", failedMessages);

        notification.put("payload", payload);

        String messageJson = notification.toJSONString();
        sendAllAdminMessage(messageJson);
    }

    /**
     * 获取当前在线连接数
     */
    public static int getOnlineCount() {
        return onlineCount.get();
    }

    /**
     * 检查管理员是否在线
     */
    public static boolean isAdminOnline(String adminId) {
        return webSocketMap.containsKey(adminId);
    }
}